package com.community.consumer.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;
import com.community.common.entity.GroupRecord;
import com.community.common.entity.Order;
import com.community.common.entity.OrderSerial;
import com.community.common.entity.vo.UserLoginVo;
import com.community.common.result.Result;
import com.community.consumer.config.AlibaConfig;
import com.community.consumer.entity.vo.AlipayTradePagePayModel;
import com.community.consumer.service.ConsumerService;
import com.community.consumer.service.UserService;
import com.community.consumer.service.impl.InformationImpl;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/alipay")
@Log4j2
public class AliPayController {

    @Autowired
    ConsumerService consumerService;

    @Autowired
    UserService userService;

    @Autowired
    RedisTemplate<String,Object> redisTemplate;

    @Autowired
    HttpServletRequest request;

    @Autowired
    ConsumerController consumerController;

    /**
     * 回调
     * @param request
     * @return
     */
    @Transactional
    @PostMapping("/notify")
    public Result alyNotifyUrl(HttpServletRequest request) throws AlipayApiException {
        log.info("请求路径：【{}】，请求方式:【{}】",
                request.getRequestURI(),request.getMethod());
        AlibaConfig alibaConfig = new AlibaConfig();
        Result result=null;

        /**
         * 回调返回的数据为 支付成功
         */
        if (request.getParameter("trade_status").equals("TRADE_SUCCESS")) {
            System.out.println("=========支付宝异步回调========");

            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
            }
            System.out.println(params);

            String outTradeNo = params.get("out_trade_no");
            String gmtPayment = params.get("gmt_payment");
            String alipayTradeNo = params.get("trade_no");

            // 签名
            String sign = params.get("sign");
            String content = AlipaySignature.getSignCheckContentV1(params);

            /**
             * 验签
             */
            boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, alibaConfig.getALIPAY_PUBLIC_KEY(), "UTF-8"); // 验证签名
            // 验签通过
            if (checkSignature) {
                // 获取调用返回的数据
                System.out.println("交易名称: " + params.get("subject"));
                System.out.println("交易状态: " + params.get("trade_status"));
                System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
                System.out.println("商户订单号: " + params.get("out_trade_no"));
                System.out.println("交易金额: " + params.get("total_amount"));
                System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
                System.out.println("买家付款时间: " + params.get("gmt_payment"));
                System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));
                // 根据流水号查询订单
                OrderSerial orderSerial = consumerService.findOrderSerial(outTradeNo);
                // 修改订单流水
                consumerService.updateOrderSerial(outTradeNo,1);

                // 查询订单
                Order order = consumerService.selectOne(orderSerial.getOrderNum());

                //订单不为空且状态为未支付（防止重复添加积分）
                if (order != null && order.getStatus() ==0) {
                    // 修改支付时间
                    order.setUpdateTime(new Date());
                    // 保存成功的交易流水
                    order.setSerialNum(orderSerial.getSerialNum());
                    //修改订单状态为支付成功
                    order.setStatus(2);
                    //修改订单状态
                    consumerService.updateOrderSuccess(order);
                    // 此订单为拼团
                    if(order.getType()==1){
                        // 查询拼团能否继续参加
                        int status = consumerService.findGroupGood(order.getGroupId());
                        // 拼团可正常参与
                        if(status == 0 ) {
                            order.setDelFlag(1);
                            consumerController.joinGroupOverPay(order);
                            //用户添加积分
                            userService.updateById(order);
                        }
                        // 拼团已失效 退款
                        if(status == 1) {
                            order.setDelFlag(9);
                            consumerController.joinGroupOverPay(order);
                            // 退款处理
                            // order（订单在）
                        }
                    }
                    result = Result.success("支付成功");
                }
            }
            // 验签失败
            if(!checkSignature){
                result = Result.error("验签失败");
            }
        }
        // 回调结果为支付失败
        if(request.getParameter("trade_status").equals("TRADE_DEFEATE")){
            System.out.println("=========支付宝异步回调========");

            Map<String, String> params = new HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();
            for (String name : requestParams.keySet()) {
                params.put(name, request.getParameter(name));
            }

            String outTradeNo = params.get("out_trade_no");
            String gmtPayment = params.get("gmt_payment");
            String alipayTradeNo = params.get("trade_no");

            // 签名
            String sign = params.get("sign");
            String content = AlipaySignature.getSignCheckContentV1(params);

            /**
             * 验签
             */
            boolean checkSignature = AlipaySignature.rsa256CheckContent(content, sign, alibaConfig.getALIPAY_PUBLIC_KEY(), "UTF-8"); // 验证签名
            // 验签通过
            if (checkSignature) {
                // 获取调用返回的数据
                System.out.println("交易名称: " + params.get("subject"));
                System.out.println("交易状态: " + params.get("trade_status"));
                System.out.println("支付宝交易凭证号: " + params.get("trade_no"));
                System.out.println("商户订单号: " + params.get("out_trade_no"));
                System.out.println("交易金额: " + params.get("total_amount"));
                System.out.println("买家在支付宝唯一id: " + params.get("buyer_id"));
                System.out.println("买家付款时间: " + params.get("gmt_payment"));
                System.out.println("买家付款金额: " + params.get("buyer_pay_amount"));

                // 根据流水号查询订单
                OrderSerial orderSerial = consumerService.findOrderSerial(outTradeNo);
                // 修改订单流水
                consumerService.updateOrderSerial(outTradeNo,2);
                result = Result.error("支付失败");
            }
            // 验签失败
            if(!checkSignature){
                result = Result.error("验签失败");
            }
        }

        return result;

    }

    /**
     * 支付
     * @return
     */
    @SneakyThrows
    @PostMapping("/toPayByAliBaba")
    public Result toPayByAliBaba(@RequestBody AlipayTradePagePayModel payMoneyForEntity){
        // 支付宝调用配置
        AlibaConfig alibaConfig = new AlibaConfig();

        AlipayClient alipayClient = new DefaultAlipayClient(alibaConfig.getURL(),alibaConfig.getAPPID(),alibaConfig.getPRIVATE_KEY(),
                alibaConfig.getFORMAT(),alibaConfig.getCHARSET(),alibaConfig.getALIPAY_PUBLIC_KEY(),alibaConfig.getSIGN_TYPE());

        AlipayTradePagePayRequest aliRequest = new AlipayTradePagePayRequest();
        // 回调地址
        aliRequest.setNotifyUrl(alibaConfig.getNotifyUrl());
        aliRequest.setReturnUrl(alibaConfig.getReturnUrl());

        JSONObject jsonObject = new JSONObject();
        OrderSerial orderSerial = new OrderSerial();

        // 查找订单总价
        Double totalAmount = consumerService.findOrderMoreAllPrice(payMoneyForEntity.getOrderNum());

        payMoneyForEntity.setTotalAmount(totalAmount);
        // 流水号
        Date date = new Date();
        SimpleDateFormat format = new SimpleDateFormat("YYYYMMdd");
        String format1 = format.format(date);
        String s = RandomUtil.randomNumbers(20);
        format1 = format1 + s;

        // 创建人
        UserLoginVo userLoginVo = InformationImpl.findUserLogin(redisTemplate, request);

        orderSerial.setCreateBy(userLoginVo.getName());
        orderSerial.setOrderNum(payMoneyForEntity.getOrderNum());
        orderSerial.setPayPrice(totalAmount);
        orderSerial.setSerialNum(format1);
        // 保存流水
        consumerService.saveOrderSerial(orderSerial);

        // 订单号
        jsonObject.put("out_trade_no",format1);
        // 该支付金额
        jsonObject.put("total_amount", payMoneyForEntity.getTotalAmount());
        // 支付主题
        jsonObject.put("subject", payMoneyForEntity.getSubject());
        // 商品信息
        jsonObject.put("product_code",payMoneyForEntity.getProductCode());

        aliRequest.setBizContent(jsonObject.toString());
        AlipayTradePagePayResponse response = alipayClient.pageExecute(aliRequest);

        Result<String> result=null;
        if(response.isSuccess()){
            // 调用成功返回的表单数据
            String body = alipayClient.pageExecute(aliRequest).getBody();
            result=Result.success(body);
        }else {
            System.out.println("调用失败");
            result=Result.error();
        }
        log.info("请求路径：【{}】，请求方式：【{}】，响应结果：【{}】",
                request.getRequestURI(),request.getMethod(),result);
        return result;
    }
}
